#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <strings.h>
#include <pcre.h>

#include <common.h>
#include <regular_expression.h>


#ifdef	USE_REG_EXP

static const char *
get_replace_str(const char *reg_rep_to);

bool
str_replace_once(char *str,int offset,int len,const char *substr);

bool
regular_expression(char *src,const char *reg_exp_str)
{
	//这个简易引擎主要用来完成这个练习项目，保留一定的扩展性
	if(NULL == src || NULL == reg_exp_str) {
		return false;
	}
	//判断首字母必须是s或者m
	if('s' != reg_exp_str[0] && 'm' != reg_exp_str[0]) {
		return false;
	}
	//第二个字符必须是'/'
	if('/' != reg_exp_str[1]) {
		return false;
	}
	////基本处理
	const char *p = reg_exp_str + 2;
	int tmp_inx = 0,s_inx = 0;
	int split_count = 0;//分隔符的个数
	//分隔符的对应的字符串位置索引
	int split_c_index[2] = {0};
	while('\0' != p[tmp_inx]) {
		if('/' == p[tmp_inx] && 
			'\\' != *(p + tmp_inx - 1)) {
			split_count++;
			if(split_count > 2)
				break;
			split_c_index[s_inx++] = tmp_inx + 2;
		}
		tmp_inx++;
	}
	bool ret = false;
	//replace
	if('s' == reg_exp_str[0]) {
		//前面没有'\'的'/'必须有两个
		if(2 != split_count) {
			return ret;
		}
		//分别获取两个表达式
		int reg_rep_from_len = split_c_index[0] - 1;
		int reg_rep_to_len = split_c_index[1] - split_c_index[0];
		char *reg_rep_from = (char *)malloc(reg_rep_from_len);
		char *reg_rep_to = (char *)malloc(reg_rep_to_len);
		bzero(reg_rep_from,reg_rep_from_len);
		bzero(reg_rep_to,reg_rep_to_len);
		memcpy(reg_rep_from,reg_exp_str + 2,split_c_index[0] - 2);
		memcpy(reg_rep_to,reg_exp_str + split_c_index[0] + 1,
					split_c_index[1] - split_c_index[0] - 1);
		//DEBUG_PRINT("reg1:[%s],reg2:[%s]\n",reg_rep_from,reg_rep_to);
		//然后对表达式进行进一步的处理
		//首先对表达式进行处理，得到适合进行匹配的数据结构
		const char *reg_error = NULL;
		int erroffset = 0;
		pcre *p_reg_from = pcre_compile(reg_rep_from,0,&reg_error,&erroffset,NULL);
		if(NULL == p_reg_from) {
			fprintf(stderr,"error in complie %s at pos %d.error:%s\n",
									reg_rep_from,erroffset,reg_error);
			return ret;
		}
		//然后是执行这个正则表达式得到一些匹配结果
		int ovectorsize = strlen(src);//这个必须被修正为3的倍数，是该函数的要求
		if(ovectorsize % 3 != 0) {
			//需要进行补齐
			ovectorsize += 3 - ovectorsize % 3;
		}
		int *ovector = (int *)malloc(ovectorsize * 4);
		bzero(ovector,ovectorsize * 4);
		int match_count;
	LOOP:
		match_count = pcre_exec(p_reg_from,NULL,src,strlen(src),
										0,0,ovector,ovectorsize);
		if(match_count < 0) {
			if(match_count != PCRE_ERROR_NOMATCH) {
				fprintf(stderr,"pcre_exec ret %d\n",match_count);
			}
			goto EXIT_REGEXP;
		}
		//DEBUG_PRINT("match_count:%d\n",match_count);
		if(match_count < 1) {
			goto EXIT_REGEXP_SUCCESS;
		}
		//有匹配就根据位置进行字符串替换
		//根据正则表达式构造字符串
		const char *s = get_replace_str(reg_rep_to);
		if(NULL == s && NULL == reg_rep_to) {
			goto EXIT_REGEXP;
		}
		int i;
		const char **listptr;
		pcre_get_substring_list(src,ovector,match_count,&listptr);
		for(i = 0;i < match_count;++i) {
			ret = str_replace_once(src,ovector[0],strlen(listptr[i]),s);
			if(false == ret) {
				goto EXIT_REGEXP;
			}
		}
		pcre_free_substring_list(listptr);
		goto LOOP;
	EXIT_REGEXP_SUCCESS:
		ret = true;
	EXIT_REGEXP:
		free(reg_rep_from);
		free(reg_rep_to);
		free(p_reg_from);
		free(ovector);
		return ret;
	} else if('m' == reg_exp_str[0]) {
		//前面没有'\'的'/'必须有一个
		if(1 != split_count) {
			return ret;
		}
		//分别获取两个表达式
		int reg_rep_from_len = split_c_index[0] - 1;
		char *reg_rep_from = (char *)malloc(reg_rep_from_len);
		bzero(reg_rep_from,reg_rep_from_len);
		memcpy(reg_rep_from,reg_exp_str + 2,split_c_index[0] - 2);
		//DEBUG_PRINT("reg1:[%s]\n",reg_rep_from);
		//首先对表达式进行处理，得到适合进行匹配的数据结构
		const char *reg_error = NULL;
		int erroffset = 0;
		pcre *p_reg_from = pcre_compile(reg_rep_from,0,&reg_error,&erroffset,NULL);
		if(NULL == p_reg_from) {
			fprintf(stderr,"error in complie %s at pos %d.error:%s\n",
									reg_rep_from,erroffset,reg_error);
			return ret;
		}
		//然后是执行这个正则表达式得到一些匹配结果
		int ovectorsize = strlen(src);//这个必须被修正为3的倍数，是该函数的要求
		if(ovectorsize % 3 != 0) {
			//需要进行补齐
			ovectorsize += 3 - ovectorsize % 3;
		}
		int *ovector = (int *)malloc(ovectorsize * 4);
		bzero(ovector,ovectorsize * 4);
		int match_count = pcre_exec(p_reg_from,NULL,src,strlen(src),
										0,0,ovector,ovectorsize);
		if(match_count < 0) {
			if(match_count != PCRE_ERROR_NOMATCH) {
				fprintf(stderr,"pcre_exec ret %d\n",match_count);
			}
			goto EXIT_REGEXP_M;
		}
		if(match_count < 1) {
			goto EXIT_REGEXP_M;
		}
		ret = true;
	EXIT_REGEXP_M:
		free(reg_rep_from);
		free(p_reg_from);
		free(ovector);
		return ret;
	}
	return ret;
}

/*主要是每个字符以及长度，不定长的不应当进行替换
//+ *不能算然后是字符必须确定.之前必须有\\*/
static const char *
get_replace_str(const char *reg_rep_to)
{
	if(NULL == reg_rep_to || 0 == \
			strlen(reg_rep_to)) {
		return NULL;
	}
	int r_len = strlen(reg_rep_to) + 1;
	char *r_str_buf = (char *)malloc(r_len);
	bzero(r_str_buf,r_len);
	int i,j;bool trope_flag = false;
	for(i = 0,j = 0;'\0' != reg_rep_to[i];++i) {
		if('\\' == reg_rep_to[i]) {
			if(!trope_flag) {
				trope_flag = true; 
				continue;
			}
		}
		if(trope_flag) {
			r_str_buf[j++] = reg_rep_to[i];
			trope_flag = false;
		} else if('+' == reg_rep_to[i] || \
					'*' == reg_rep_to[i]) {
			free(r_str_buf);
			return NULL;
		} else {
			r_str_buf[j++] = reg_rep_to[i];
		}
	}
	return r_str_buf;
}

bool
str_replace_once(char *str,int offset,int len,const char *substr)
{
	int i = 0,j = 0;
	int sublen = 0;
	if(NULL == substr) {
		//相当于删除字符串
		sublen = 0;
	} else {
		sublen = strlen(substr);
		//首先直接复制，然后剩下的直接进行前移
		strcpy(str + offset,substr);
	}
	for(i = sublen,j = 0;'\0' != *(str + offset + len + j);++i,++j) {
		*(str + offset + i) = *(str + offset + len + j);
	}
	*(str + offset + i) = '\0';
	return true;
}

#endif
